package info.batcloud.fanli.core.service.impl;

import com.ctospace.archit.common.pagination.Paging;
import info.batcloud.fanli.core.domain.Result;
import info.batcloud.fanli.core.domain.stat.CommissionOrderAllotEarning;
import info.batcloud.fanli.core.dto.CityAgentDTO;
import info.batcloud.fanli.core.dto.CommissionOrderAddDTO;
import info.batcloud.fanli.core.dto.CommissionOrderDTO;
import info.batcloud.fanli.core.dto.DistrictAgentDTO;
import info.batcloud.fanli.core.entity.CommissionItem;
import info.batcloud.fanli.core.entity.CommissionOrder;
import info.batcloud.fanli.core.entity.User;
import info.batcloud.fanli.core.entity.UserCommissionOrder;
import info.batcloud.fanli.core.enums.*;
import info.batcloud.fanli.core.event.CommissionOrderChangeEvent;
import info.batcloud.fanli.core.helper.CollectionHelper;
import info.batcloud.fanli.core.mapper.stat.CommissionOrderMapper;
import info.batcloud.fanli.core.repository.CommissionItemRepository;
import info.batcloud.fanli.core.repository.CommissionOrderRepository;
import info.batcloud.fanli.core.repository.UserCommissionOrderRepository;
import info.batcloud.fanli.core.repository.UserRepository;
import info.batcloud.fanli.core.service.*;
import info.batcloud.fanli.core.settings.CommissionAllotSetting;
import info.batcloud.fanli.core.settings.CommissionSettlementSetting;
import info.batcloud.fanli.core.settings.IntegralSetting;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommissionOrderServiceImpl implements CommissionOrderService {

    private static final Logger logger = LoggerFactory.getLogger(CommissionOrderServiceImpl.class);

    @Inject
    private UserRepository userRepository;

    @Inject
    private UserCommissionOrderRepository userCommissionOrderRepository;

    @Inject
    private TmpFileService tmpFileService;

    @Inject
    private CommissionOrderRepository commissionOrderRepository;

    @Inject
    private CommissionService commissionService;

    @Inject
    private CommissionItemRepository commissionItemRepository;

    @Inject
    private WalletService walletService;

    @Inject
    private UserService userService;

    @Inject
    private SystemSettingService systemSettingService;

    @Inject
    private AgentService agentService;

    @Inject
    private CommissionOrderService commissionOrderService;

    @Inject
    private ApplicationEventPublisher applicationEventPublisher;

    @Inject
    private ActivityService activityService;

    @Inject
    private CommissionOrderMapper commissionOrderMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void saveCommissionOrderList(List<CommissionOrderAddDTO> list) {
        if (list.size() == 0) {
            return;
        }
        List<String> orderNos = new ArrayList<>();
        List<Long> itemIds = list.stream().map(o -> {
            orderNos.add(o.getOrderNo());
            return Long.valueOf(o.getItemId());
        }).collect(Collectors.toList());
        List<EcomPlat> ecomPlatList = new ArrayList<>();
        CommissionOrderAddDTO firstOrder = list.get(0);
        if (firstOrder.getEcomPlat() == EcomPlat.TAOBAO || firstOrder.getEcomPlat() == EcomPlat.TMALL) {
            ecomPlatList.addAll(Arrays.asList(EcomPlat.TAOBAO, EcomPlat.TMALL));
        } else if (firstOrder.getEcomPlat() == EcomPlat.JD) {
            ecomPlatList.add(EcomPlat.JD);
        } else if (firstOrder.getEcomPlat() == EcomPlat.PDD) {
            ecomPlatList.add(EcomPlat.PDD);
        }
        List<CommissionItem> commissionItemList = commissionItemRepository
                .findBySourceItemIdInAndEcomPlatIn(itemIds, ecomPlatList);
        Map<Long, CommissionItem> commissionItemMapByItemId = new HashMap<>();
        for (CommissionItem commissionItem : commissionItemList) {
            commissionItemMapByItemId.put(commissionItem.getSourceItemId(), commissionItem);
        }
        List<CommissionOrder> eList = commissionOrderRepository
                .findByEcomPlatInAndOrderNoIn(ecomPlatList, orderNos);
        Map<String, CommissionOrder> commissionOrderMapByOrderNo = new HashMap<>();
        /**
         * 这里订单匹配已有订单的时候，如果用户一个订单有多个商品，则会有多个订单记录，那么这里就需要匹配订单NO+商品id，这样能够确认
         * 唯一一条记录
         * */
        for (CommissionOrder co : eList) {
            commissionOrderMapByOrderNo.put(co.getOrderNo() + "-" + co.getItemId(), co);
        }
        List<CommissionOrder> orderList = new ArrayList<>();
        for (CommissionOrderAddDTO tbkCo : list) {
            CommissionOrder co;
            String coKey = tbkCo.getOrderNo() + "-" + tbkCo.getItemId();
            if (commissionOrderMapByOrderNo.containsKey(coKey)) {
                //说明订单已经存在,进行更新操作
                co = commissionOrderMapByOrderNo.get(coKey);
                /**
                 * 如果订单已经结算，那么就不做处理
                 * 这里非常重要，不然会产生重复结算的情况
                 * */
                if (co.getStatus() == CommissionOrderStatus.SETTLED
                        || co.getStatus() == CommissionOrderStatus.INVALID) {
                    continue;
                }
            } else {
                //不存在，进行新增操作
                co = new CommissionOrder();
            }
            Long originUserId = co.getUserId();
            BeanUtils.copyProperties(tbkCo, co);
            if (originUserId != null) {
                co.setUserId(originUserId);
            }
            if (commissionItemMapByItemId.containsKey(Long.valueOf(tbkCo.getItemId()))) {
                CommissionItem commissionItem = commissionItemMapByItemId.get(Long.valueOf(tbkCo.getItemId()));
                co.setItemPicUrl(commissionItem.getPicUrl());
                co.setCommissionItemId(commissionItem.getId());
            }
            orderList.add(co);
        }
        this.commissionOrderRepository.save(orderList);
        for (CommissionOrder co : orderList) {
            if (co.getUserId() != null) {
                User user = userRepository.findOne(co.getUserId());
                this.allocateCommissionOrderToUser(user, co);
            }
            CommissionOrderChangeEvent event = new CommissionOrderChangeEvent(co.getId());
            this.applicationEventPublisher.publishEvent(event);
        }
    }

    private Result allocateCommissionOrderToUser(User user, CommissionOrder co) {
        /**
         * 检查commissionOrder是否已经进行过分佣，如果已经进行过分佣，则不再进行分佣操作；
         * */
        Result result = new Result();
        if (co.isAllocated()) {
            result.setSuccess(false);
            result.setMsg("该订单已经进行过分佣，无法再次进行分佣！");
            return result;
        }
        co.setUserId(user.getId());
        co.setAllocated(true);
        commissionOrderRepository.save(co);
        CommissionAllotSetting commissionAllotSetting
                = systemSettingService.findActiveSetting(CommissionAllotSetting.class);
        /**
         * 检查订单是否参与免单，如果参与了免单，则不进行分佣操作。
         * */
        if (co.getCommissionItemId() != null &&
                activityService.isCommissionItemJoinFlashSaleWithUser(user.getId(), co.getCommissionItemId())) {
            logger.info("判断到订单参与免单活动,userId:" + user.getId() + ", commissionItemId:" + co.getCommissionItemId());
            UserCommissionOrder uco = new UserCommissionOrder();
            uco.setCommissionOrder(co);
            uco.setCommissionRate(0f);
            uco.setCreateTime(new Date());
            uco.setUserId(user.getId());
            uco.setAllotType(CommissionAllotType.SELF_BUY); //自购订x单
            userCommissionOrderRepository.save(uco);
            result.setSuccess(true);
            return result;
        }
        //如果当前用户不是plus会员，则生成一条返利为0的直推订单。这里是为了供用户查询
        if (user.getLevel().level < UserLevel.PLUS.level) {
            UserCommissionOrder uco = new UserCommissionOrder();
            uco.setCommissionOrder(co);
            uco.setCommissionRate(0f);
            uco.setCreateTime(new Date());
            uco.setUserId(user.getId());
            uco.setAllotType(CommissionAllotType.SELF_BUY); //自购订x单
            userCommissionOrderRepository.save(uco);
        }
        if (user.getRelationList().size() == 0) {
            result.setSuccess(true);
            return result;
        }
        List<UserCommissionOrder> ucoList = new ArrayList<>();
        /**
         * 首先进行代理分佣
         * 1、关系代理（服务商分佣）
         * 2、县级代理
         * 3、市级代理
         * */
        long topUserId = user.getRelationList().get(0);
        //如果关系链的顶级是运营商，那么则需要对运营商进行分佣操作，生成运营商订单
        if (agentService.isAgent(topUserId, AgentType.RELATION)
                && commissionAllotSetting.getRelationAgentCommissionRate() > 0) {
            UserCommissionOrder uco = new UserCommissionOrder();
            uco.setCommissionOrder(co);
            uco.setCommissionRate(commissionAllotSetting.getRelationAgentCommissionRate());
            uco.setCreateTime(new Date());
            uco.setUserId(topUserId);
            uco.setAllotType(CommissionAllotType.RELATION_AGENT);
            ucoList.add(uco);
        }
        //生成市级代理订单
        if (user.getCityId() != null) {
            //市级代理商分佣
            CityAgentDTO cityAgent = agentService.findCityAgentByCityId(user.getCityId());
            if (cityAgent != null && agentService.isValid(cityAgent)
                    && commissionAllotSetting.getCityAgentCommissionRate() > 0) {
                UserCommissionOrder uco = new UserCommissionOrder();
                uco.setCommissionOrder(co);
                uco.setCommissionRate(commissionAllotSetting.getCityAgentCommissionRate());
                uco.setCreateTime(new Date());
                uco.setUserId(cityAgent.getUser().getId());
                uco.setAllotType(CommissionAllotType.CITY_AGENT);
                ucoList.add(uco);
            }
            //县级代理商分佣
            if (user.getDistrictId() != null
                    && commissionAllotSetting.getDistrictAgentCommissionRate() > 0) {
                DistrictAgentDTO districtAgent = agentService.findDistrictAgentByDistrictId(user.getDistrictId());
                if (districtAgent != null && agentService.isValid(districtAgent)) {
                    UserCommissionOrder uco = new UserCommissionOrder();
                    uco.setCommissionOrder(co);
                    uco.setCommissionRate(commissionAllotSetting.getDistrictAgentCommissionRate());
                    uco.setCreateTime(new Date());
                    uco.setUserId(districtAgent.getUser().getId());
                    uco.setAllotType(CommissionAllotType.DISTRICT_AGENT);
                    ucoList.add(uco);
                }
            }
        }
        //关系链进行分佣
        List<Long> relationIds = user.getRelationList();
        Collections.reverse(relationIds);//倒转
        List<Long> plusRelationIds = userService.filterUserLevelUserIds(relationIds, UserLevel.PLUS);
        for (int i = 0; i < plusRelationIds.size(); i++) {
            UserCommissionOrder uco = new UserCommissionOrder();
            uco.setCommissionOrder(co);
            uco.setCreateTime(new Date());
            uco.setUserId(plusRelationIds.get(i));
            uco.setAllotType(uco.getUserId().equals(user.getId()) ? CommissionAllotType.DIRECT : CommissionAllotType.INDIRECT);
            if (i == 0) {
                uco.setCommissionRate(commissionAllotSetting.getPlusCommissionRate());
            } else if (i == 1) {
                uco.setCommissionRate(commissionAllotSetting.getPlusParentCommissionRate());
            } else if (i == 2) {
                uco.setCommissionRate(commissionAllotSetting.getPlusGrandParentCommissionRate());
            }
            if (uco.getCommissionRate() != null
                    && uco.getCommissionRate() > 0) {
                ucoList.add(uco);
            }
            //最多分3层
            if (i >= 2) {
                break;
            }
        }
        //运营商分佣
        List<Long> carrierIds = userService.filterUserLevelUserIds(relationIds, UserLevel.CARRIER);
        for (int i = 0; i < carrierIds.size(); i++) {
            long userId = carrierIds.get(i);
            UserCommissionOrder uco = new UserCommissionOrder();
            uco.setCommissionOrder(co);
            uco.setCreateTime(new Date());
            uco.setUserId(userId);
            uco.setAllotType(CommissionAllotType.CARRIER);
            if (i == 0) {
                uco.setCommissionRate(commissionAllotSetting.getCarrierCommissionRate());
            } else if (i == 1) {
                uco.setCommissionRate(commissionAllotSetting.getCarrierParentCommissionRate());
            }
            if (uco.getCommissionRate() != null
                    && uco.getCommissionRate() > 0) {
                ucoList.add(uco);
            }
            //最多分2层
            if (i >= 1) {
                break;
            }
        }
        //运营总监分佣
        List<Long> chiefIds = userService.filterUserLevelUserIds(relationIds, UserLevel.CHIEF);
        for (int i = 0; i < chiefIds.size(); i++) {
            long userId = chiefIds.get(i);
            UserCommissionOrder uco = new UserCommissionOrder();
            uco.setCommissionOrder(co);
            uco.setCreateTime(new Date());
            uco.setUserId(userId);
            uco.setAllotType(CommissionAllotType.CHIEF);
            if (i == 0) {
                uco.setCommissionRate(commissionAllotSetting.getChiefCommissionRate());
            } else if (i == 1) {
                uco.setCommissionRate(commissionAllotSetting.getChiefParentCommissionRate());
            }
            if (uco.getCommissionRate() != null
                    && uco.getCommissionRate() > 0) {
                ucoList.add(uco);
            }
            //最多分2层
            if (i >= 1) {
                break;
            }
        }
        if (ucoList.size() > 0) {
            CommissionSettlementSetting settlementSetting
                    = systemSettingService.findActiveSetting(CommissionSettlementSetting.class);
            for (UserCommissionOrder uco : ucoList) {
                uco.setCommissionRewardRate(settlementSetting.getRewardCommissionRate());
            }
            this.userCommissionOrderRepository.save(ucoList);
        }
        result.setSuccess(true);
        return result;
    }

    @Override
    @Transactional
    public synchronized void settle() {
        logger.info("开始进行订单结算");
        int total = 0;
        while (true) {
            /**
             * 淘宝订单本身是本月20号结算上个月的订单，所有这里也需要如此,
             * 京东和淘宝规则一样
             * */
            List<CommissionOrder> commissionOrderList = commissionOrderRepository
                    .findTop1000ByStatusAndPlatSettledTimeBeforeOrderByIdAsc(CommissionOrderStatus.WAIT_SETTLE, DateUtils.truncate(new Date(), Calendar.MONTH));
            logger.info("读取到代结算的订单：" + commissionOrderList.size());
            for (CommissionOrder commissionOrder : commissionOrderList) {
                commissionOrderService.settleCommissionOrder(commissionOrder.getId());
            }
            total += commissionOrderList.size();
            if (commissionOrderList.size() <= 1000) {
                break;
            }
        }
        logger.info("订单结算完成，共结算：" + total + "个订单");
    }

    @Override
    @Transactional
    public synchronized void settleCommissionOrder(long commissionOrderId) {
        CommissionOrder commissionOrder = commissionOrderRepository.findOne(commissionOrderId);
        settleCommissionOrder(commissionOrder);
    }

    @Override
    public int countValidCommissionOrderNumByUserId(long userId) {
        return this.commissionOrderRepository.countByUserIdAndStatusIn(userId, CommissionOrderStatus.WAIT_SETTLE, CommissionOrderStatus.SETTLED, CommissionOrderStatus.PAID);
    }

    @Override
    public Paging<CommissionOrderDTO> search(SearchParam param) {
        Specification<CommissionOrder> specification = (root, query, cb) -> {
            Predicate predicate = cb.conjunction();
            List<Expression<Boolean>> expressions = predicate.getExpressions();
            if (param.getUserId() != null) {
                expressions.add(cb.equal(root.get("userId"), param.getUserId()));
            }
            if (param.getStatus() != null) {
                expressions.add(cb.equal(root.get("status"), param.getStatus()));
            }
            if (param.getCommissionItemId() != null) {
                expressions.add(cb.equal(root.get("commissionItemId"), param.getCommissionItemId()));
            }
            if (param.getEcomPlat() != null) {
                expressions.add(cb.equal(root.get("ecomPlat"), param.getEcomPlat()));
            }
            if (StringUtils.isNotBlank(param.getOrderNo())) {
                expressions.add(cb.equal(root.get("orderNo"), param.getOrderNo()));
            }
            if (param.getMinCreateTime() != null) {
                expressions.add(cb.greaterThanOrEqualTo(root.get("createTime"), param.getMinCreateTime()));
            }
            if (param.getMaxCreateTime() != null) {
                expressions.add(cb.lessThanOrEqualTo(root.get("createTime"), param.getMaxCreateTime()));
            }
            if (param.getMinSettledTime() != null) {
                expressions.add(cb.greaterThanOrEqualTo(root.get("settledTime"), param.getMinSettledTime()));
            }
            if (param.getMaxSettledTime() != null) {
                expressions.add(cb.lessThanOrEqualTo(root.get("settledTime"), param.getMaxSettledTime()));
            }
            if (param.getItemId() != null) {
                expressions.add(cb.equal(root.get("itemId"), param.getItemId()));
            }
            if (StringUtils.isNotBlank(param.getItemTitle())) {
                expressions.add(cb.like(root.get("itemTitle"), "%" + param.getItemTitle() + "%"));
            }
            return predicate;
        };
        Sort sort;
        if (param.getSort() != null) {
            switch (param.getSort()) {
                case ID_DESC:
                    sort = new Sort(Sort.Direction.DESC, "id");
                    break;
                case SETTLED_TIME_DESC:
                    sort = new Sort(Sort.Direction.DESC, "settledTime");
                    break;
                case COMMISSION_FEE_ASC:
                    sort = new Sort(Sort.Direction.ASC, "commissionFee");
                    break;
                case COMMISSION_FEE_DESC:
                    sort = new Sort(Sort.Direction.DESC, "commissionFee");
                    break;
                case COMMISSION_RATE_ASC:
                    sort = new Sort(Sort.Direction.ASC, "commissionRate");
                    break;
                case COMMISSION_RATE_DESC:
                    sort = new Sort(Sort.Direction.DESC, "commissionRate");
                    break;
                default:
                    sort = new Sort(Sort.Direction.DESC, "id");
            }
        } else {
            sort = new Sort(Sort.Direction.DESC, "id");
        }
        Pageable pageable = new PageRequest(param.getPage() - 1,
                param.getPageSize(), sort);
        Page<CommissionOrder> page = commissionOrderRepository.findAll(specification, pageable);
        List<CommissionOrderDTO> dtoList = toBOList(page.getContent());
        if (param.isFetchAllotEarning()) {
            List<Long> ids = dtoList.stream().map(o -> o.getId()).collect(Collectors.toList());
            if (ids.size() > 0) {
                List<CommissionOrderAllotEarning> list = commissionOrderMapper.statAllotEarningByCommissionOrderIds(ids);
                Map<Long, CommissionOrderAllotEarning> map = CollectionHelper.toMap(list, CommissionOrderAllotEarning::getCommissionOrderId);
                dtoList.forEach(d -> d.setAllotEarning(map.get(d.getId())));
            }
        }
        return Paging.of(dtoList, Long.valueOf(page.getTotalElements()).intValue(),
                param.getPage(), param.getPageSize());
    }

    @Override
    public Result allocateCommissionOrderToUser(long userId, long commissionOrderId) {
        User user = userRepository.findOne(userId);
        CommissionOrder co = commissionOrderRepository.findOne(commissionOrderId);
        return allocateCommissionOrderToUser(user, co);
    }

    private static String[] TITLE_LIST = new String[]{
            "商品ID",
            "商品名称",
            "会员ID",
            "用户昵称",
            "手机号",
            "平台",
            "金额",
            "数量",
            "订单号",
            "预估",
            "预估比",
            "佣金",
            "佣金比",
            "创建时间",
            "结算时间",
            "总分配",
            "总人数",
            "总奖励",
            "总佣金",
            "总比例",
            "总结算佣金",
            "总结算奖励",
            "总结算",
            "订单状态"
    };

    @Override
    public File exportCommissionOrder(ExportParam param) throws IOException {
        File excelFile = tmpFileService.createFile("order_" + System.currentTimeMillis() + ".xls");
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet();
        sheet.autoSizeColumn(1, true);
        HSSFFont boldFond = workbook.createFont();
        boldFond.setBold(true);
        boldFond.setFontHeightInPoints((short) 16);
        CellStyle foldStyle = workbook.createCellStyle();
        CellStyle commonStyle = workbook.createCellStyle();
        HSSFFont commonFont = workbook.createFont();
        commonFont.setFontHeightInPoints((short) 14);
        commonStyle.setFont(commonFont);
        foldStyle.setFont(boldFond);
        HSSFRow titleRow = sheet.createRow(0);
        for (int i = 0; i < TITLE_LIST.length; i++) {
            HSSFCell titleCell = titleRow.createCell(i);
            //给单元格设置内容
            titleCell.setCellValue(TITLE_LIST[i]);
            titleCell.setCellStyle(foldStyle);
        }
        int page = 1;
        int pageSize = param.getMaxCount() < 100 ? param.getMaxCount() : 100;
        int maxPage = (param.getMaxCount() + pageSize - 1) / pageSize;
        int rowIndex = 1;
        param.setPageSize(pageSize);
        while (true) {
            param.setPage(page);
            Paging<CommissionOrderDTO> paging = this.search(param);
            for (CommissionOrderDTO dto : paging.getResults()) {
                HSSFRow row = sheet.createRow(rowIndex++);
                row.setHeightInPoints(20);
                for (int i = 0; i < TITLE_LIST.length; i++) {
                    HSSFCell rowCell = row.createCell(i);
                    rowCell.setCellStyle(commonStyle);
                    switch (TITLE_LIST[i]) {
                        case "商品ID":
                            rowCell.setCellValue(dto.getItemId());
                            break;
                        case "商品名称":
                            rowCell.setCellValue(dto.getItemTitle());
                            break;
                        case "会员ID":
                            if (dto.getUserId() != null) {
                                rowCell.setCellValue(dto.getUserId());
                            }
                            break;
                        case "用户昵称":
                            if (dto.getUserNickname() != null) {
                                rowCell.setCellValue(dto.getUserNickname());
                            }
                            break;
                        case "手机号":
                            if (dto.getUserPhone() != null) {
                                rowCell.setCellType(CellType.STRING);
                                rowCell.setCellValue(dto.getUserPhone());
                            }
                            break;
                        case "平台":
                            rowCell.setCellValue(dto.getEcomPlatTitle());
                            break;
                        case "金额":
                            rowCell.setCellType(CellType.NUMERIC);
                            rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getPayFee())));
                            break;
                        case "数量":
                            rowCell.setCellType(CellType.NUMERIC);
                            rowCell.setCellValue(dto.getItemNum());
                            break;
                        case "订单号":
                            rowCell.setCellValue(dto.getOrderNo());
                            break;
                        case "预估":
                            rowCell.setCellType(CellType.NUMERIC);
                            rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getEstimateCommissionFee())));
                            break;
                        case "预估比":
                            rowCell.setCellType(CellType.NUMERIC);
                            rowCell.setCellValue(dto.getEstimateCommissionRate());
                            break;
                        case "创建时间":
                            rowCell.setCellValue(DateFormatUtils.format(dto.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
                            break;
                        case "结算时间":
                            if (dto.getSettledTime() != null) {
                                rowCell.setCellValue(DateFormatUtils.format(dto.getSettledTime(), "yyyy-MM-dd HH:mm:ss"));
                            }
                            break;
                        case "总分配":
                            if (dto.getAllotFee() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getAllotFee())));
                            }
                            break;
                        case "总人数":
                            if (dto.getAllotEarning() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(dto.getAllotEarning().getUserCommissionOrderNum());
                            }
                            break;
                        case "佣金":
                            if (dto.getCommissionFee() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getCommissionFee())));
                            }
                            break;
                        case "佣金比":
                            if (dto.getCommissionRate() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(String.format("%.2f", dto.getCommissionRate()));
                            }
                            break;
                        case "总奖励":
                            if (dto.getAllotEarning() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getAllotEarning().getTotalUserRewardFee())));
                            }
                            break;
                        case "总佣金":
                            if (dto.getAllotEarning() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getAllotEarning().getTotalUserCommissionFee())));
                            }
                            break;
                        case "总比例":
                            if (dto.getAllotEarning() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(dto.getAllotEarning().getTotalUserCommissionRate());
                            }
                            break;
                        case "总结算佣金":
                            if (dto.getAllotEarning() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getAllotEarning().getTotalSettledCommissionFee())));
                            }
                            break;
                        case "总结算奖励":
                            if (dto.getAllotEarning() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getAllotEarning().getTotalSettledRewardFee())));
                            }
                            break;
                        case "总结算":
                            if (dto.getAllotEarning() != null) {
                                rowCell.setCellType(CellType.NUMERIC);
                                rowCell.setCellValue(String.valueOf(String.format("%.2f", dto.getAllotEarning().getTotalSettledFee())));
                            }
                            break;
                        case "订单状态":
                            rowCell.setCellValue(dto.getStatusTitle());
                            break;
                    }
                }
            }
            if (!paging.getHasNext()) {
                break;
            }
            if (page >= maxPage) {
                break;
            }
            page++;
        }
        for (int i = 0; i < TITLE_LIST.length; i++) {
            sheet.autoSizeColumn(i);
        }
        workbook.write(excelFile);
        return excelFile;
    }

    private List<CommissionOrderDTO> toBOList(List<CommissionOrder> commissionOrderList) {
        List<CommissionOrderDTO> commissionOrderDTOList = new ArrayList<>();
        List<Long> userIdList = commissionOrderList.stream().map(c -> c.getUserId()).filter(id -> id != null).collect(Collectors.toList());
        List<User> userList = userRepository.findByIdIn(userIdList);
        Map<Long, User> userMap = new HashMap<>(10);
        for (User user : userList) {
            userMap.put(user.getId(), user);
        }
        for (CommissionOrder commissionOrder : commissionOrderList) {
            CommissionOrderDTO bo = new CommissionOrderDTO();
            BeanUtils.copyProperties(commissionOrder, bo);
            User user = userMap.get(bo.getUserId());
            if (user != null) {
                bo.setUserAvatarUrl(user.getAvatarUrl());
                bo.setUserNickname(user.getNickname());
                bo.setUserPhone(user.getPhone());
            }
            commissionOrderDTOList.add(bo);
        }
        return commissionOrderDTOList;
    }

    private void settleCommissionOrder(CommissionOrder commissionOrder) {
        if (commissionOrder.getStatus() != CommissionOrderStatus.WAIT_SETTLE) {
            throw new RuntimeException("订单状态不是带结算状态，不能结算");
        }
        logger.info(String.format("开始结算订单：ID:%s, commissionFee:%s",
                new Object[]{commissionOrder.getId().toString(), commissionOrder.getCommissionFee().toString()}));
        List<UserCommissionOrder> userCommissionOrderList = userCommissionOrderRepository.findByCommissionOrderId(commissionOrder.getId());
        IntegralSetting integralSetting = systemSettingService.findActiveSetting(IntegralSetting.class);
        Date now = new Date();
        for (UserCommissionOrder userCommissionOrder : userCommissionOrderList) {
            logger.info(String.format("开始结算用户订单：commissionRate:%s", new Object[]{userCommissionOrder.getCommissionRate().toString()}));
            float commissionFee = commissionOrder.getCommissionFee() * userCommissionOrder.getCommissionRate() / 100;
            userCommissionOrder.setSettledCommissionFee(commissionFee);
            userCommissionOrder.setSettledRewardFee(0f);
            /**
             * 积分奖励结算
             * */
            if (userCommissionOrder.getCommissionRewardRate() > 0) {
                //奖励金额
                float rewardFee = commissionService.determineRewardCommissionFee(userCommissionOrder.getCommissionRewardRate(), commissionFee);
                float integral = walletService.exchangeMoneyToIntegral(rewardFee);
                if (integral > 0) {
                    WalletService.WalletConsumeResult consumeResult = walletService.consumeIntegral(userCommissionOrder.getUserId(), integral,
                            WalletFlowDetailType.COMMISSION_SETTLE_EXCHANGE_MONEY, userCommissionOrder.getId() + "");
                    if (consumeResult.isSuccess()) {
                        userCommissionOrder.setSettledRewardFee(rewardFee);
                    } else {
                        logger.info("积分不足，无法进行结算奖励");
                    }
                }
            }
            userCommissionOrder.setSettledFee(userCommissionOrder.getSettledCommissionFee()
                    + userCommissionOrder.getSettledRewardFee());
            userCommissionOrder.setSettledTime(now);
            logger.info(String.format("用户结算收入：佣金：%s，奖励：%s，结算收入：%s", new Object[]{commissionFee, userCommissionOrder.getSettledRewardFee(),
                    userCommissionOrder.getSettledFee()}));
            walletService.addMoney(userCommissionOrder.getUserId(), commissionFee,
                    WalletFlowDetailType.COMMISSION_SETTLEMENT, userCommissionOrder.getId() + "");
            if (userCommissionOrder.getSettledRewardFee() > 0) {
                walletService.addMoney(userCommissionOrder.getUserId(), userCommissionOrder.getSettledRewardFee(),
                        WalletFlowDetailType.COMMISSION_SETTLE_REWARD, userCommissionOrder.getId() + "");
            }
            /**
             * 直推订单生成积分，积分是总金额
             * */
            if (userCommissionOrder.getAllotType() == CommissionAllotType.DIRECT) {
                if (integralSetting.getCommissionEachFeeIntegral() != 0) {
                    float val = Float.valueOf(commissionOrder.getCommissionFee() * integralSetting.getCommissionEachFeeIntegral());
                    logger.info(String.format("生成用户积分：%s", new Object[]{val}));
                    if (val > 0) {
                        walletService.addIntegral(userCommissionOrder.getUserId(),
                                val, WalletFlowDetailType.USER_COMMISSION_INTEGRAL, userCommissionOrder.getId() + "");
                    }

                }
            }
        }
        userCommissionOrderRepository.save(userCommissionOrderList);
        commissionOrder.setStatus(CommissionOrderStatus.SETTLED);
        commissionOrder.setSettledTime(now);
        float allotFee = 0f;
        for (UserCommissionOrder userCommissionOrder : userCommissionOrderList) {
            allotFee += userCommissionOrder.getSettledFee();
        }
        commissionOrder.setAllotFee(allotFee);
        commissionOrderRepository.save(commissionOrder);
        logger.info(String.format("订单结算完成：ID:%s,commissionFee:%s",
                new Object[]{commissionOrder.getId().toString(), commissionOrder.getCommissionFee().toString()}));
    }

}
